Frontend.ctrl.login = function() {
	var store = {

	// filter default option
	}, _filter = function(self) {
		var i = self,
			s = i.parent().find('span'),
			v = i.val();

		if(v.length > 0) s.hide();
		else s.fadeIn('fast');

	// bind for filter
	}, fields = function() {
		$('input[type="text"], input[type="password"]', '#login').each(function() {
			var self = $(this);

			_filter(self);
			self.on('input', function(){ _filter(self); });
		});

		$('select', '#login').simpleselect();

	// validate email
	}, validate = function(email) {
		var re = /\S+@\S+\.\S+/;
		return re.test(email);

	// correctly redirect after login or signup
	}, _redirect = function() {
		if(window.LOGIN_LOCATION) Frontend.go(window.LOGIN_LOCATION);
		else history.go(-1);

	// on form submit intercept
	}, intercept = function() {
		// login form
		$('form#form_login', '#login').on('submit', function(e){
			e.preventDefault();
			var post = $(this).serialize(),
				b = $('button', '#form_login');

			// for every form field
			$('input[type="text"], input[type="password"]', '#form_login').each(function() {
				var o = $(this);
					n = o.attr('name'),
					N = n.charAt(0).toUpperCase() + n.substr(1);

				// remove errors
				o.removeClass('error');

				// check if blank
				if(!$.trim(o.val()).length > 0) {
					Frontend.noty({type: 'error', text: N +' is blank'});
					o.addClass('error');
					o.val('');
					_filter(o);

				// filled?
				} else {
					// check valid email
					if(o.attr('name') == 'email' && !validate(o.val())) {
						Frontend.noty({type: 'error', text: N +' is invalid'});
						o.addClass('error');
					}
				}
			});

			// check for errors
			var error = false;
			$('input[type="text"], input[type="password"]', '#form_login').each(function() {
				if($(this).hasClass('error'))
					error = true;
			});

			// stop if errors found
			if(error)
				return false;

			// do login procedure
			b.attr('disabled', 'disabled');
			Frontend.ajax({type: 'post', data: post, url: 'login/auth',
				success: function(data) {
					b.removeAttr('disabled');

					// send message
					Frontend.noty({type: 'information', text: 'Successfully logged in!'});

					// transform auth tile into profile tile
					Frontend.metro(function() {
						// broadcast message and redirect
						Frontend.socket.noty({type: 'information', text: data.user.name + ' logged in!'});
						_redirect();
					});
				}, error: function() {
					b.removeAttr('disabled');

					// send message
					Frontend.noty({type: 'error', text: 'Authentication error'});

					// add error to fields
					$('input[type="text"], input[type="password"]', '#form_login').each(function() {
						$(this).addClass('error');
					});
				}
			});
		});

		// signup form
		$('form#form_signup', '#login').on('submit', function(e){
			e.preventDefault();
			var post = $(this).serialize(),
				b = $('button', '#form_signup');

			// check name and email with ajax again
			checkName($('input[name="name"]', '#form_signup'), function() {
				checkEmail($('input[name="email"]', '#form_signup'), function() {
					// for every form field
					$('input[type="text"], input[type="password"]', '#form_signup').each(function() {
						var o = $(this);
							n = o.attr('name'),
							N = n.charAt(0).toUpperCase() + n.substr(1);

						// remove errors (except for name and email because they were already checked with ajax)
						if(o.attr('name') != 'name' && o.attr('name') != 'email')
							o.removeClass('error');

						// check if blank
						if(!$.trim(o.val()).length > 0) {
							Frontend.noty({type: 'error', text: N +' is blank'});
							o.addClass('error');
							o.val('');
							_filter(o);
						}
					});

					// check for password confirm
					var c = $('input[name="confirm"]', '#form_signup');
					if($.trim(c.val()).length > 0 && $('input[name="password"]', '#form_signup').val() != c.val()) {
						Frontend.noty({type: 'error', text: 'Passwords don\'t match'});
						c.addClass('error');
					}

					// check for errors
					var error = false;
					$('input[type="text"], input[type="password"]', '#form_signup').each(function() {
						if($(this).hasClass('error'))
							error = true;
					});

					// stop if errors found
					if(error)
						return false;

					// do signup procedure
					b.attr('disabled', 'disabled');
					Frontend.ajax({type: 'post', data: post, url: 'login/signup', success: function(data){
						b.removeAttr('disabled');

						// send & broadcast message
						Frontend.noty({type: 'information', text: 'Account created!<br />Successfully logged in!'});

						// transform auth tile into profile tile
						Frontend.metro(function() {
							// broadcast message and redirect
							Frontend.socket.noty({type: 'information', text: data.user.name + ' logged in!'});
							_redirect();
						});
					}});
				});
			});
		});

	// bind events
	}, bind = function() {
		// name validation function
		var _name = function() {
			var o = $(this);
			if(!$.trim(o.val()).length > 0)
				return false;

			Frontend.ajax({type: 'post', data: {name: o.val()}, url: 'login/check',
				success: function(){ o.addClass('valid'); },
				error: function(){ o.addClass('error'); }
			});

		// email validation function
		}, _email = function() {
			var o = $(this);
			if($.trim(o.val()).length > 0)
				if(!validate(o.val()))
					return o.addClass('error');

			Frontend.ajax({type: 'post', data: {email: o.val()}, url: 'login/check',
				success: function(){ o.addClass('valid'); },
				error: function(){ o.addClass('error'); }
			});
		};

		// on any input change, loose the error
		$('input[type="text"], input[type="password"]', '#login').on('input', function() {
			$(this).removeClass();
		});

		// validate login email in pure javascript
		$('input[name="email"]', '#form_login').on('input', function(){
			var o = $(this);
			if($.trim(o.val()).length > 0)
				if(!validate(o.val()))
					o.addClass('error');
		});

		// validate signup name and email with ajax
		$('input[name="name"]', '#form_signup').on('input', $.debounce(250, _name));
		$('input[name="email"]', '#form_signup').on('input', $.debounce(250, _email));

	// check name with ajax
	}, checkName = function(self, f) {
		var o = self;

		// no value ? callback
		if(!$.trim(o.val()).length > 0)
			return f();

		// do ajax
		Frontend.ajax({type: 'post', data: {name: o.val()}, url: 'login/check',
			success: function(data) {
				o.addClass('valid');
				f();
			}, error: function() {
				Frontend.noty({type: 'error', text: 'Name is taken'});
				o.removeClass().addClass('error');
				f();
			}
		});

	// check email with ajax
	}, checkEmail = function(self, f) {
		var o = self;

		// no value ? callback
		if(!$.trim(o.val()).length > 0)
			return f();

		// has value
		else {
			// invalid?
			if(!validate(o.val())) {
				o.addClass('error');
				Frontend.noty({type: 'error', text: 'Email is invalid'});
				return f();
			}
		}

		// do ajax
		Frontend.ajax({type: 'post', data: {email: o.val()}, url: 'login/check',
			success: function(data) {
				o.addClass('valid');
				f();
			}, error: function() {
				Frontend.noty({type: 'error', text: 'Email is taken'});
				o.removeClass().addClass('error');
				f();
			}
		});

	// constructor
	}, __construct = function() {
		fields();
		bind();
		intercept();

		// select first element (not a button, not hidden) from the first form
		$('form:first *:input[type!=hidden]:not(button):first').focus();
	};

	// public, yay
	return {
		init: __construct
	};
}();